/* 
 * File:   IO_Manager.h
 * Author: filipp
 *
 * Created on March 18, 2010, 9:43 PM
 *
 *
 * This is the IO Manager class. It is responsible for dealing with any events
 * related to SDL, and some of the OpenGL management/configuration stuff. For
 * example, if there's a mouse movement event, it would go through the
 * IO_Manager class, get decoded into the coordinates and relative movement,
 * and then the relevant information gets passed to the game class.
 * This class also handles things like initializing opengl, window resizing,
 * and so on.
 */

#ifndef _IO_MANAGER_H
#define	_IO_MANAGER_H


#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>
#include "GLFT_Font.hpp"

#include "misc.h"
#include <map>
#include <sstream>


#define GAME_RATE 20
//20 ms per game step

class Context;

class MouseInfo{
public:
	MouseInfo(const vec2i& sSize=vec2i(0,0)) : left(false), right(false), middle(false),
			screenSize(sSize) {}
	void update(SDL_MouseMotionEvent& mouseMove);
	void update(SDL_MouseButtonEvent& mouseClick);
	vec2i mouseRawPosition;
	vec2i mouseCartesianPosition;
	vec2i mouseRawRelative;
	vec2i mouseCartesianRelative;
	vec2i screenSize;
	bool left, right, middle;
};

class IO_Manager{
public:
	IO_Manager(); //when created, this class does nothing
	~IO_Manager();
	bool initialize_SDL(); //return true on success, also sets up opengl
	bool initializeFont(const std::string& filename, unsigned size);
	void handleEvents(); //handle events
	int startMainLoop(Uint32 delay);// delay is number of ms between steps (ideally)
	size_t registerContext(Context& context);
	void registerGameContext(Context& context);
	void deregisterContext(size_t cID);
	void deregisterGameContext();
	void screenCoordinates(); //0,0 is upper left, y axis increases as you go down
	void cartesianCoordinates(); //0,0 is lower left, y increases as you go up
private:
//functions
	void GL_Init(int width=640, int height=480); //sets up the window with default opengl
	void screenRefreshFunc();
	void doDrawFps();
//members
	SDL_Surface* screen;
	SDL_Event event;
	GLFT_Font default_font; //i hope this doesn't break
	std::map<size_t, autoInitPtr<Context> > contexts;
	Context* gameContext;
	size_t contextID;

	SDL_TimerID screenTimer;
	SDL_TimerID gameTimer;
	Uint32 lastScreenRefreshTicks;
	
	MouseInfo mouseinfo;
	
	vec2i screenSize;

	Uint32 startTicks;
	int scheduledRefresh;

	smoothTracer<float> fps;
	Uint32 fpsCap; //minimum delay between frames
//flags
	bool drawFps; //should we draw fps stats?
	bool keepRunning;
};

Uint32 ScreenTimerFunc(Uint32 rate, void* param);
Uint32 GameTimerFunc(Uint32 rate, void* param);




class Context{
public:
	Context();
	Context(const vec2i& p, const vec2i& s);
	virtual ~Context();
	virtual void renderToScreen(); //opengl calls to update what this thing shows
	virtual void renderToScreen(std::stringstream& out);
	virtual void updateState();
	virtual void move(const vec2i& p);
	virtual void moveRel(const vec2i& p);
	virtual void resize(const vec2i& s);
	virtual bool isOccupied(const vec2i& point); //does point fall inside the area of this thing?
	virtual bool isOccupied(const vec2i& upperLeft, const vec2i& lowerRight); //does this rectangle intersect this context?
	virtual void processKey(SDL_KeyboardEvent& kbe);
	virtual void processMouse(SDL_MouseButtonEvent& mouseButton, const MouseInfo& mouseinfo); //process position and clicks
	virtual void processMouse(const MouseInfo& mouseinfo); //process position and button state only
protected:
	vec2i position; //upper left corner
	vec2i size; //width and height
};


#endif	/* _IO_MANAGER_H */




